package nl.weeaboo.sh.editor.area;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToggleButton;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import nl.weeaboo.sh.level.Level;
import nl.weeaboo.sh.model.AreaModel;
import nl.weeaboo.sh.model.RoomEnemyModel;
import nl.weeaboo.sh.model.RoomModel;
import nl.weeaboo.sh.model.TileSetIndex;
import timon.common.components.BigPopupCombo;
import timon.common.components.IconListCellRenderer;

@SuppressWarnings("serial")
public class Palette extends JPanel {

	public enum Mode {
		TILE, ROOM, ENEMY;
	}
	
	private AreaModel area;
	
	private List<SelectionListener> listeners;
	private JPanel northWestPanel;
	private JComboBox modeCombo;
	private JPanel leftPanel;
	private JPanel mainPanel;
	
	private JList tileSetBrowser;
	private TileSetPanel tileSetPanel;
	private JScrollPane tileSetMainPane;
	
	private RoomBrowser roomBrowser;
	private JPanel roomLeftPanel;
	private RoomToolPanel roomToolPanel;
	
	private EnemyBrowser enemyBrowser;
	
	public Palette() {
		listeners = new LinkedList<SelectionListener>();
	
		modeCombo = new BigPopupCombo(Mode.values());
		modeCombo.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				onModeChanged();
			}
		});
				
		northWestPanel = new JPanel(new BorderLayout(5, 5));
		
		createTileModeComponents();
		createRoomModeComponents();
		createEnemyModeComponents();
		
		leftPanel = new JPanel(new BorderLayout(5, 5));
		leftPanel.setPreferredSize(new Dimension(200, 200));
		
		mainPanel = new JPanel(new BorderLayout(5, 5));
		mainPanel.setPreferredSize(new Dimension(200, 200));

		setLayout(new BorderLayout(5, 5));
		add(leftPanel, BorderLayout.WEST);
		add(mainPanel, BorderLayout.CENTER);
		
		onModeChanged();
	}
	
	//Functions
	public void dispose() {
		tileSetPanel.dispose();
	}
	
	protected void createTileModeComponents() {
		tileSetBrowser = new JList();
		tileSetBrowser.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		tileSetBrowser.setCellRenderer(new IconListCellRenderer() {
			public Image getImageFor(Object object) {
				return null;
			}
			public String getLabelFor(Object object) {
				if (object instanceof EditorTileSet) {
					EditorTileSet tileSet = (EditorTileSet)object;
					return tileSet.getId();
				}
				return "<html><i><font color='#555555'>Delete</font></i></html>";
			}
		});
		tileSetBrowser.addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent e) {
				tileSetPanel.setSelected((EditorTileSet)tileSetBrowser.getSelectedValue());
			}
		});
		
		tileSetPanel = new TileSetPanel();
		tileSetPanel.addListener(new SelectionListener() {
			public void onSelected(Object object) {
				fireSelectionChanged(object);
			}
		});
		
		tileSetMainPane = new JScrollPane(tileSetPanel);
		tileSetMainPane.getHorizontalScrollBar().setUnitIncrement(Level.tileSize / 2);
		tileSetMainPane.getVerticalScrollBar().setUnitIncrement(Level.tileSize / 2);
		tileSetMainPane.getVerticalScrollBar().setBlockIncrement(4);		
	}
	protected void createRoomModeComponents() {
		JButton addRoomButton = new JButton("Add");
		addRoomButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				area.addRoom(new RoomModel(area.generateRoomId()));
				onRoomsChanged();
			}
		});

		final JButton removeRoomButton = new JButton("Remove");
		removeRoomButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				RoomModel room = (RoomModel)roomBrowser.getSelectedValue();
				if (room != null) {
					area.removeRoom(room);
					onRoomsChanged();
				}
			}
		});
		
		roomBrowser = new RoomBrowser();
		roomBrowser.addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent e) {
				RoomModel room = (RoomModel)roomBrowser.getSelectedValue();
				roomToolPanel.setSelectedRoom(area, room);
				fireSelectionChanged(room);
			}
		});
				
		JPanel buttonPanel = new JPanel(new GridLayout(-1, 2, 5, 5));
		buttonPanel.add(addRoomButton);
		buttonPanel.add(removeRoomButton);
		
		roomLeftPanel = new JPanel(new BorderLayout(5, 5));
		roomLeftPanel.add(new JScrollPane(roomBrowser), BorderLayout.CENTER);
		roomLeftPanel.add(buttonPanel, BorderLayout.SOUTH);
		
		roomToolPanel = new RoomToolPanel(this);
	}

	protected void createEnemyModeComponents() {		
		enemyBrowser = new EnemyBrowser();
		enemyBrowser.addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent e) {
				RoomEnemyModel enemy = (RoomEnemyModel)enemyBrowser.getSelectedValue();
				fireSelectionChanged(enemy);
			}
		});
	}
	
	public void createNorthWestPanel(final TilePanel tilePanel) {
		final JToggleButton bgButton = new JToggleButton("BG");
		bgButton.setSelected(tilePanel.getDrawBackground());
		bgButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				tilePanel.setDrawBackground(bgButton.isSelected());
			}
		});
		
		final JToggleButton fgButton = new JToggleButton("FG");
		fgButton.setSelected(tilePanel.getDrawForeground());
		fgButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				tilePanel.setDrawForeground(fgButton.isSelected());
			}
		});
		
		JPanel viewPanel = new JPanel(new GridLayout(-1, 2, 0, 0));
		viewPanel.add(bgButton); viewPanel.add(fgButton);
		
		northWestPanel.removeAll();
		northWestPanel.add(modeCombo, BorderLayout.CENTER);
		northWestPanel.add(viewPanel, BorderLayout.EAST);
		
		onModeChanged();
	}
	
	protected void onRoomsChanged() {
		roomBrowser.setArea(area);
	}
	
	public void onRoomChanged(RoomModel room) {
		repaint();
	}
	
	protected void onModeChanged() {
		leftPanel.removeAll();
		leftPanel.add(northWestPanel, BorderLayout.NORTH);
		mainPanel.removeAll();

		Mode m = getMode();
		if (m == Mode.TILE) {
			leftPanel.add(new JScrollPane(tileSetBrowser), BorderLayout.CENTER);
			mainPanel.add(tileSetMainPane, BorderLayout.CENTER);
		} else if (m == Mode.ROOM) {
			leftPanel.add(roomLeftPanel, BorderLayout.CENTER);
			mainPanel.add(roomToolPanel, BorderLayout.CENTER);
		} else if (m == Mode.ENEMY) {
			leftPanel.add(new JScrollPane(enemyBrowser), BorderLayout.CENTER);
		}
		
		validate();
		repaint();		
	}
	
	public void addListener(SelectionListener l) {
		listeners.add(l);
	}
	public void removeListener(SelectionListener l) {
		listeners.remove(l);
	}

	protected void fireSelectionChanged(final Object obj) {
		for (SelectionListener l : listeners) {
			l.onSelected(obj);
		}
	}
	
	//Getters
	public Mode getMode() {
		return (Mode)modeCombo.getSelectedItem();
	}
	
	//Setters
	public void setArea(AreaModel area, Map<String, EditorTileSet> ts) {
		this.area = area;
		
		DefaultListModel listModel = new DefaultListModel();
		listModel.addElement(null);
		for (EditorTileSet ets : ts.values()) {
			listModel.addElement(ets);
		}
		tileSetBrowser.setModel(listModel);		
		tileSetPanel.setTileSets(ts);

		onRoomsChanged();
	}
	public void setSelectedTile(TileSetIndex tsi) {
		modeCombo.setSelectedItem(Mode.TILE);
		if (tsi == null) {
			tileSetBrowser.setSelectedIndex(0);
		} else {
			for (int n = 0; n < tileSetBrowser.getModel().getSize(); n++) {
				EditorTileSet ets = (EditorTileSet)tileSetBrowser.getModel().getElementAt(n);
				if (ets != null && ets.getId().equals(tsi.getTileSet().getId())) {
					tileSetBrowser.setSelectedValue(ets, true);
				}
			}
		}
		tileSetPanel.setSelectedTile(tsi);
	}
	public void setSelectedEnemy(RoomEnemyModel e) {
		modeCombo.setSelectedItem(Mode.ENEMY);
		if (e == null) {
			enemyBrowser.setSelectedIndex(0);
		} else {
			for (int n = 0; n < enemyBrowser.getModel().getSize(); n++) {
				RoomEnemyModel rem = (RoomEnemyModel)enemyBrowser.getModel().getElementAt(n);
				if (rem != null && rem.getClassName().equals(e.getClassName())) {
					enemyBrowser.setSelectedValue(rem, true);
				}
			}
		}
	}
	
}
